/**
 *
 */
package com.angel.email.attachments.manager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.activation.DataHandler;
import javax.mail.Message;
import javax.mail.MessagingException;

import com.angel.common.keyValue.KeyValueResult;
import com.angel.common.keyValue.impl.KeyValueResultImpl;
import com.angel.email.attachments.strategies.AttachmentsStrategy;
import com.angel.email.attachments.strategies.impl.multiple.MultiPartsAttachmentsStrategy;
import com.angel.email.attachments.strategies.impl.simple.PlainTextAttachmentStrategy;
import com.angel.email.constants.MimeTypePropertyConstants;
import com.angel.email.exceptions.EmailAttachmentException;
import com.angel.webapp.file.FileInformation;



/**
 * @author William
 * @since 14/August/2009
 *
 */
public class EmailAttachmentManager {
	private KeyValueResult attachmentStrategies;

	public EmailAttachmentManager(){
		super();
		this.attachmentStrategies = new KeyValueResultImpl();
		this.initializeMultiplesAttachmentsStrategies();
		this.initializeSimplesAttachmentsStrategies();
	}

	private void initializeSimplesAttachmentsStrategies() {
		this.attachmentStrategies.addKeyValue(MimeTypePropertyConstants.TEXT_PLAIN_MIME_TYPE, new PlainTextAttachmentStrategy());
		this.attachmentStrategies.addKeyValue(MimeTypePropertyConstants.TEXT_HTML_MIME_TYPE, new PlainTextAttachmentStrategy());
	}

	private void initializeMultiplesAttachmentsStrategies() {
		this.attachmentStrategies.addKeyValue(MimeTypePropertyConstants.MULTIPART_ALTERNATIVE_MIME_TYPE, new MultiPartsAttachmentsStrategy());
		this.attachmentStrategies.addKeyValue(MimeTypePropertyConstants.MULTIPART_MIXED_MIME_TYPE, new MultiPartsAttachmentsStrategy());
		this.attachmentStrategies.addKeyValue(MimeTypePropertyConstants.MULTIPART_RELATED_MIME_TYPE, new MultiPartsAttachmentsStrategy());
	}

	protected AttachmentsStrategy getAttachmentStrategy(String contentType){
		return getAttachmentStrategy(this.attachmentStrategies, contentType);
	}

	public static AttachmentsStrategy getAttachmentStrategy(KeyValueResult attachmentStrategies, String contentType) throws EmailAttachmentException {
		AttachmentsStrategy multipleAttachmentStrategy = (AttachmentsStrategy) attachmentStrategies.getResultFor(contentType);
		if(multipleAttachmentStrategy == null){
			Collection<String> mimesType = attachmentStrategies.findAllKeys();
			for(String mimeType : mimesType){
				if(contentType.indexOf(mimeType) > -1){
					return (AttachmentsStrategy) attachmentStrategies.getResultFor(mimeType);
				}
			}
			throw new EmailAttachmentException("Cannot found attachment strategy for mime type [" + contentType + "].");
		}
		return multipleAttachmentStrategy;
	}

	public FileInformation getFirstAttachmentFor(Message message) throws EmailAttachmentException {
		return this.getAttachmentFor(message, 1);
	}

	public FileInformation getAttachmentFor(Message message) throws EmailAttachmentException {
		try {
			String contentType = message.getContentType();
			AttachmentsStrategy simpleAttachmentStrategy = getAttachmentStrategy(contentType);
			DataHandler dataHandler = message.getDataHandler();
			return simpleAttachmentStrategy.getAttachmentFrom(dataHandler);
		} catch (MessagingException e) {
			//TODO Write comments.
			throw new EmailAttachmentException("", e);
		}
	}

	public FileInformation getAttachmentFor(Message message, Integer number) throws EmailAttachmentException {
		List<FileInformation> attachments = this.getAttachmentsFor(message);
		if(attachments.size() < number){
			//TODO Write comments.
			throw new EmailAttachmentException("");
		}
		return attachments.get(number - 1);
	}

	public List<FileInformation> getAttachmentsFor(Message[] messages) throws MessagingException, IOException {
		List<FileInformation> totalAttachments = new ArrayList<FileInformation>();
		for(Message m: messages){
			List<FileInformation> attachments = this.getAttachmentsFor(m);
			totalAttachments.addAll(attachments);
		}
		return totalAttachments;
	}

	public List<FileInformation> getAttachmentsFor(Message message) throws EmailAttachmentException {
		String contentType;
		try {
			contentType = message.getContentType();
			DataHandler dataHandler = message.getDataHandler();
			AttachmentsStrategy attachmentStrategy = this.getAttachmentStrategy(contentType);
			return attachmentStrategy.getAttachmentsFrom(dataHandler, this.attachmentStrategies);
		} catch (MessagingException e) {
			//TODO Write comments.
			throw new EmailAttachmentException("", e);
		}
	}
}
